From d05ba53afec82308edcfeb778446010bf18e71ae Mon Sep 17 00:00:00 2001 From: skeleten Date: Sun, 26 Jun 2016 15:03:08 +0200 Subject: [PATCH] Add color support for Windows consoles. Fixes #2803 --- src/cargo/core/shell.rs | 58 +++++++++++++++++++++++++++++++---------- src/cargo/lib.rs | 8 +++--- tests/shell.rs | 8 +++--- 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs index dbe854a09..b7996a36a 100644 --- a/src/cargo/core/shell.rs +++ b/src/cargo/core/shell.rs @@ -147,27 +147,57 @@ impl MultiShell { } impl Shell { - pub fn create(out: Box, config: ShellConfig) -> Shell { + pub fn create Box>(mut out_fn: T, config: ShellConfig) -> Shell { + let term = match Shell::get_term(out_fn()) { + Ok(t) => t, + Err(_) => NoColor(out_fn()) + }; + + Shell { + terminal: term, + config: config, + } + } + + #[cfg(any(windows))] + fn get_term(out: Box) -> CargoResult { + // Check if the creation of a console will succeed + if ::term::WinConsole::new(vec![0u8; 0]).is_ok() { + let t = try!(::term::WinConsole::new(out)); + if !t.supports_color() { + Ok(NoColor(Box::new(t))) + } else { + Ok(Colored(Box::new(t))) + } + } else { + // If we fail to get a windows console, we try to get a `TermInfo` one + Ok(Shell::get_terminfo_term(out)) + } + } + + #[cfg(any(unix))] + fn get_term(out: Box) -> CargoResult { + Ok(Shell::get_terminfo_term(out)) + } + + fn get_terminfo_term(out: Box) -> AdequateTerminal { // Use `TermInfo::from_env()` and `TerminfoTerminal::supports_color()` // to determine if creation of a TerminfoTerminal is possible regardless // of the tty status. --color options are parsed after Shell creation so // always try to create a terminal that supports color output. Fall back // to a no-color terminal regardless of whether or not a tty is present // and if color output is not possible. - Shell { - terminal: match ::term::terminfo::TermInfo::from_env() { - Ok(ti) => { - let term = TerminfoTerminal::new_with_terminfo(out, ti); - if !term.supports_color() { - NoColor(term.into_inner()) - } else { - // Color output is possible. - Colored(Box::new(term)) - } - }, - Err(_) => NoColor(out), + match ::term::terminfo::TermInfo::from_env() { + Ok(ti) => { + let term = TerminfoTerminal::new_with_terminfo(out, ti); + if !term.supports_color() { + NoColor(term.into_inner()) + } else { + // Color output is possible. + Colored(Box::new(term)) + } }, - config: config, + Err(_) => NoColor(out), } } diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index 2db31fe76..746089548 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -36,7 +36,7 @@ use core::shell::Verbosity::{Verbose}; use core::shell::ColorConfig::{Auto}; use term::color::{BLACK}; -pub use util::{CargoError, CliError, CliResult, human, Config, ChainError}; +pub use util::{CargoError, CargoResult, CliError, CliResult, human, Config, ChainError}; macro_rules! bail { ($($fmt:tt)*) => ( @@ -137,16 +137,14 @@ pub fn shell(verbosity: Verbosity, color_config: ColorConfig) -> MultiShell { } let tty = isatty(Output::Stderr); - let stderr = Box::new(io::stderr()); let config = ShellConfig { color_config: color_config, tty: tty }; - let err = Shell::create(stderr, config); + let err = Shell::create(|| Box::new(io::stderr()), config); let tty = isatty(Output::Stdout); - let stdout = Box::new(io::stdout()); let config = ShellConfig { color_config: color_config, tty: tty }; - let out = Shell::create(stdout, config); + let out = Shell::create(|| Box::new(io::stdout()), config); return MultiShell::new(out, err, verbosity); diff --git a/tests/shell.rs b/tests/shell.rs index 40471f0bf..549070d41 100644 --- a/tests/shell.rs +++ b/tests/shell.rs @@ -28,7 +28,7 @@ fn non_tty() { let config = ShellConfig { color_config: Auto, tty: false }; let a = Arc::new(Mutex::new(Vec::new())); - Shell::create(Box::new(Sink(a.clone())), config).tap(|shell| { + Shell::create(|| Box::new(Sink(a.clone())), config).tap(|shell| { shell.say("Hey Alex", color::RED).unwrap(); }); let buf = a.lock().unwrap().clone(); @@ -43,7 +43,7 @@ fn color_explicitly_disabled() { let config = ShellConfig { color_config: Never, tty: true }; let a = Arc::new(Mutex::new(Vec::new())); - Shell::create(Box::new(Sink(a.clone())), config).tap(|shell| { + Shell::create(|| Box::new(Sink(a.clone())), config).tap(|shell| { shell.say("Hey Alex", color::RED).unwrap(); }); let buf = a.lock().unwrap().clone(); @@ -58,7 +58,7 @@ fn colored_shell() { let config = ShellConfig { color_config: Auto, tty: true }; let a = Arc::new(Mutex::new(Vec::new())); - Shell::create(Box::new(Sink(a.clone())), config).tap(|shell| { + Shell::create(|| Box::new(Sink(a.clone())), config).tap(|shell| { shell.say("Hey Alex", color::RED).unwrap(); }); let buf = a.lock().unwrap().clone(); @@ -75,7 +75,7 @@ fn color_explicitly_enabled() { let config = ShellConfig { color_config: Always, tty: false }; let a = Arc::new(Mutex::new(Vec::new())); - Shell::create(Box::new(Sink(a.clone())), config).tap(|shell| { + Shell::create(|| Box::new(Sink(a.clone())), config).tap(|shell| { shell.say("Hey Alex", color::RED).unwrap(); }); let buf = a.lock().unwrap().clone(); -- 2.30.2